#Skytank project
#Author: Leo Szeto
#Last updated: 2/8/2011
#Abstract: Skype controlled telepresense robot. Can be ordered to move across terrain wherever wifi is available.

#Dedicated to Michelle, for being my inspiration for this project.

#Import python libraries
import math
import time
import string

#Import wrapper libraries
import Skype4Py #Netbook -> Internet layer
import serial   #Netbook -> Circuits layer

#Import custom libraries
import Skytank_utils

#Keeps track of the system's state
sys_state = 0

#----------------------------------------------------
#INITIALIZATION - SKYPE
#----------------------------------------------------
#Create an instance of the Skype class
skype = Skype4Py.Skype()

#If skype is not running, go ahead and run it.
#(DOES NOT WORK) Inquire about that.
if not skype.Client.IsRunning:
	print "Client is not running."
	skype.Client.Start()

#connect to the Skype class, if this is the script's
#first run, it will most likely ask for permission.
skype.Attach()
print "Skype wrapper is now attached."
#----------------------------------------------------
#INITIALIZATION - Serial
#----------------------------------------------------
#Create an instance of the serial class and link it
#to the arduino
tries = 0
while tries < 5: #Will try up to 5 ports
	try:
		ser = serial.Serial('/dev/ttyUSB0', 9600, timeout = 0.5)
		tries = 5
	except serial.serialutil.SerialException:
		print "Failed to open Serial port!"
		tries = tries + 1
		#TO ADD: Must if it fails for the last time, exit.

print "Starting Serial interface - wait 2 seconds"
time.sleep(2) #2 second delay to allow for arduino to be ready.
#Do some handshaking to ensure that a connection
#has been made. We should write to the device first.
print "Starting handshake"
cmd = Skytank_utils.handshake(ser, 5, .25)
#Split the cmd into instr and parameters
instr = cmd[:4]
param = cmd[4:]

if instr == "ARDY":
	print "Commad: " + instr
	print "Parmeters: " + param
	sys_state = 1 				#We have successfully linked with the arduino
if instr == "FAIL":				#Use the param to figure out the failure mode
	if param == "CODE":
		print "ERROR: Invalid cmd"
	if param == "LINK":
		print "ERROR: Cannot find arduino"
	sys_state = -1;

#All systems are go. We are now ready to
while sys_state == 1:
	#Here, we'll need to start listening for both Skype and Arduino commands
	print "Listening..."
	#Let's poll skype4py to see if we have any outstanding messages and act on any jobs.

	#Should be part of the Skype init function, or run once every 5 minutes or so.
	#Grab a list of all authorized personnel (friends)
	auth_users =[]
	for user in skype.Friends:
		auth_users.append(user.Handle)

	print auth_users[0]
	chats = skype.RecentChats

	for c in chats:
		# c.Messages is a tuple, to be able to sort it,
		# convert it into a list
		msg_list = list(c.Messages)
		# Sorting based on timestamps, with custom compare function
		def message_timestamp_cmp(x, y):
			return int(y.Timestamp - x.Timestamp)
		msg_list.sort(message_timestamp_cmp)
		#Only print out messages from authorized users.
		for m in msg_list:
			for u in auth_users:
				if m.FromHandle == u:
					print m.Body
					#We can say that an instruction must be preceeded by a #
					if m.Body[:1] == '#':
						#Try sending back a message!
						#skype.CreateChatWith(u).SendMessage('Hi! I got your command! - Love, SkyTanX')
						#Also send the message to an interpreter so it gets sent to the arduino
						skypecmd = m.Body[1:] #grab the command
						if skypecmd == "LED":
							print "Sending cmd: " + skypecmd + " to arduino"
							#Instead of sending it this message, it should translate user
							#input to arduino readable cmd.
							ser.write("LEDC0000") #Toggles an LED.
							skype.CreateChatWith(u).SendMessage('I toggled an LED for you!')
						#At this point we should also probably listen for an OKAY reply from the arduino.

	sys_state = -1 #Kill script
	#Now check if we got any outstanding messages from the arduino and act on any jobs.

	#Sleepy time
	time.sleep(.5)

if sys_state == -1:
	print "Goodbye!"
